#include "Batent.h"
using namespace Batent;

namespace Batent {
namespace FS
{
    DECLARE_CMD_CLASS(CMD1, 1, 1, "fs.get_file_size",      "Get file size by return code (file size MUST < 2GB)"    );
    DECLARE_CMD_CLASS(CMD2, 1, 1, "fs.get_file_size_ex",   "Get file size by output"                                );
    DECLARE_CMD_CLASS(CMD3, 1, 1, "fs.is_directory",       "Check if is a directory");
    
}}

bool FS::is_directory(const string &szFileName)
{
    WIN32_FIND_DATA wFd;
    HANDLE hFind;

    hFind = FindFirstFile(szFileName.c_str(), &wFd);
    if (INVALID_HANDLE_VALUE != hFind && (wFd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0)
    {
        CloseHandle(hFind);
        return true;
    }

    return false;
}

bool FS::is_file_exist(const string &szFileName)
{
    WIN32_FIND_DATA wFd;
    HANDLE hFind;

    hFind = FindFirstFile(szFileName.c_str(), &wFd);
    if (INVALID_HANDLE_VALUE != hFind && (wFd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
    {
        CloseHandle(hFind);
        return true;
    }

    return false;
}

long long FS::get_file_size(const string &szFileName)
{
    HANDLE hFile;
    DWORD dSizeLow = 0;
    DWORD dSizeHigh = 0;

    hFile = CreateFile(szFileName.c_str(), FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (INVALID_HANDLE_VALUE == hFile)
    {
        error("Open file \"%s\" failed.\n", szFileName.c_str());
        return ERR_FILE_OPEN_FAIL;
    }

    dSizeLow = GetFileSize(hFile, &dSizeHigh);
    CloseHandle(hFile);

    return (long long)((INT64)dSizeHigh << 32) | dSizeLow;
}


//fs.get_file_size
int FS::CMD1::run(const vector<string> &args)
{
    long long size;

    if (!FS::is_file_exist(args[0]))
    {
        return ERR_FILE_NOT_EXIST;
    }

    size = FS::get_file_size(args[0]);
    if (size > INT_MAX)
    {
        return ERR_OUT_OF_RANGE;
    }

    return (int)(size);
}

//fs.get_file_size_ex
int FS::CMD2::run(const vector<string> &args)
{
    long long size;

    if (!FS::is_file_exist(args[0]))
    {
        return ERR_FILE_NOT_EXIST;
    }

    size = FS::get_file_size(args[0]);
    if (size < 0)
    {
        return (int)size;
    }

    print("%lld\n", size);

    return ERR_SUCCESS;
}

//fs.is_directory
int FS::CMD3::run(const vector<string> &args)
{
    if (FS::is_directory(args[0]))
    {
        return 0;
    }
    else
    {
        return -2;
    }
}
